﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace BigfootMVC.Helpers
{
    /// <summary>
    /// Generic cache class to cache object graphs and type converters
    /// </summary>
    public class ObjectCache
    {
        static Dictionary<string, object> _cache = new Dictionary<string, object>();

        public static bool Contains(String key) { return _cache.ContainsKey(key); }
        public static object GetValue(String key)
        {
            return (_cache.ContainsKey(key)) ? _cache[key] : null;
        }
        public static void Add(String key, object data)
        {
            if (_cache.ContainsKey(key))
                _cache[key] = data;
            else
                _cache.Add(key, data);
        }

        /// <summary>
        /// Get the fields / properties to hydrate for an object. 
        /// Caches the object map in order to maximize performance. 
        /// So reflection is used only first time on n object type
        /// </summary>
        /// <param name="obj">Object to use to hydrate</param>
        /// <returns>A list of Fields and Properties</returns>
        public static List<object> GetObjectFields(object obj)
        {
            var cacheKey = "reflectioncache_" + obj.GetType().FullName;
            List<object> fields;
            if (ObjectCache.Contains(cacheKey))
                fields = ObjectCache.GetValue(cacheKey) as List<object>;
            else
            {
                fields = new List<object>();
                foreach (PropertyInfo p in obj.GetType().GetProperties())
                {
                    if (p.CanWrite) fields.Add(p);
                }
                foreach (FieldInfo f in obj.GetType().GetFields())
                {
                    if (f.IsPublic && !f.IsStatic) fields.Add(f);
                }

                fields.AddRange(obj.GetType().GetFields());

                ObjectCache.Add(cacheKey, fields);
            }
            return fields;
        }
    }
}
